#include "buffer.h"

Buffer::Buffer(int initBuffSize)
    : buffer_(initBuffSize)
    , readPos_(0)
    , writePos_(0)
{

}

// 获取可写字节数
size_t Buffer::writableBytes() const
{
    return buffer_.size() - writePos_;
}

// 获取可读字节数
size_t Buffer::readableBytes() const
{
    return  writePos_ - readPos_;
}

// 获取空闲位置字节数
size_t Buffer::prependableBytes() const
{
    return readPos_;
}

// 获取可读位置指针
const char* Buffer::peek() const
{   
    return beginPtr() + readPos_;
}

// 确保有足够位置写入
void Buffer::ensureWritable(size_t len)
{
    if(writableBytes() < len) {
        makeSpace(len);
    }
    assert(writableBytes() >= len);
}

// 更新写指针
void Buffer::hasWritten(size_t len)
{   
    writePos_ += len;
}

// 读取指定长度数据
void Buffer::retrieve(size_t len)
{   
    assert(len <= readableBytes());
    readPos_ += len;
}

// 读取到指定位置
void Buffer::retrieveUntil(const char* end)
{
    assert(peek() <= end);
    retrieve(end - peek());
}

// 读取全部数据
void Buffer::retrieveAll()
{
    memset(&buffer_[0], 0, buffer_.size());
    readPos_ = 0;
    writePos_ = 0;
}

// 读取全部数据并转换为字符串形式
std::string Buffer::retrieveAllToStr()
{
    std::string str(peek(), readableBytes());
    retrieveAll();
    return str;
}

// 返回可写位置
const char* Buffer::beginWriteConst() const
{
    return beginPtr() + writePos_;
}

// 返回可写位置
char* Buffer::beginWrite()
{
    return beginPtr() + writePos_;
}

// 追加数据
void Buffer::append(const char* str, size_t len)
{
    assert(str);
    ensureWritable(len);
    std::copy(str, str + len, beginWrite());
    hasWritten(len);
}

// 追加数据
void Buffer::append(const std::string& str)
{
    append(str.data(), str.length());
}

// 追加数据
void Buffer::append(const void* data, size_t len)
{
    assert(data);
    append(static_cast<const char*>(data), len);
}

// 追加数据
void Buffer::append(const Buffer& buff)
{
    append(buff.peek(), buff.readableBytes());
}

// 将fd的数据读取到buffer_
ssize_t Buffer::readFd(int fd, int* err)
{
    char buff[65535];
    struct iovec iov[2];
    const size_t writable = writableBytes();
    // 分散读取数据
    iov[0].iov_base = beginPtr() + writePos_;
    iov[0].iov_len = writable;
    iov[1].iov_base = buff;
    iov[1].iov_len = sizeof(buff);

    const ssize_t len = readv(fd, iov, 2);
    if(len < 0) {
        *err = errno;
    } else if(static_cast<size_t>(len) <= writable) {
        writePos_ += len;
    } else {
        writePos_ = buffer_.size();
        append(buff, len - writable);
    }
    return len;
}

// 将buffer_中的数据写入到fd
ssize_t Buffer::writeFd(int fd, int* err)
{
    size_t readSize = readableBytes();
    ssize_t len = write(fd, peek(), readSize);
    if(len < 0) {
        *err = errno;
        return len;
    } 
    readPos_ += len;
    return len;
}

// 返回缓冲区的起始位置
char* Buffer::beginPtr()
{
    return &*buffer_.begin();
}

const char* Buffer::beginPtr() const
{
    return &*buffer_.begin();
}

// 缓冲区的扩容
void Buffer::makeSpace(size_t len)
{
    if(writableBytes() + prependableBytes() < len) {
        buffer_.resize(writePos_ + len + 1);
    } else {
        size_t readable = readableBytes();
        // 将可读数据置于缓冲区的开始位置
        std::copy(beginPtr() + readPos_, beginPtr() + writableBytes(), beginWrite());
        readPos_ = 0;
        writePos_ = readPos_ + readable;
        assert(readable == readableBytes());
    }
}

